﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.MountAndBlade.View.MissionViews.Singleplayer.MissionDeploymentBoundaryMarker
// Assembly: TaleWorlds.MountAndBlade.View, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 61152EB8-513B-4D4A-8AC0-0D1465C6CF6C
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\Modules\Native\bin\Win64_Shipping_Client\TaleWorlds.MountAndBlade.View.dll

using System;
using System.Collections.Generic;
using System.Linq;
using TaleWorlds.Core;
using TaleWorlds.Engine;
using TaleWorlds.Library;

#nullable disable
namespace TaleWorlds.MountAndBlade.View.MissionViews.Singleplayer
{
  public class MissionDeploymentBoundaryMarker : MissionView
  {
    public const string AttackerStaticDeploymentBoundaryName = "walk_area";
    public const string DefenderStaticDeploymentBoundaryName = "deployment_castle_boundary";
    public readonly float MarkerInterval;
    private readonly Dictionary<string, List<GameEntity>>[] boundaryMarkersPerSide = new Dictionary<string, List<GameEntity>>[2];
    private readonly IEntityFactory entityFactory;
    private bool _boundaryMarkersRemoved = true;

    public MissionDeploymentBoundaryMarker(IEntityFactory entityFactory, float markerInterval = 2f)
    {
      this.entityFactory = entityFactory;
      this.MarkerInterval = Math.Max(markerInterval, 0.0001f);
    }

    public override void AfterStart()
    {
      base.AfterStart();
      for (int index = 0; index < 2; ++index)
        this.boundaryMarkersPerSide[index] = new Dictionary<string, List<GameEntity>>();
      this._boundaryMarkersRemoved = false;
    }

    protected override void OnEndMission()
    {
      base.OnEndMission();
      this.TryRemoveBoundaryMarkers();
    }

    public override void OnInitialDeploymentPlanMadeForSide(BattleSideEnum side, bool isFirstPlan)
    {
      bool flag = this.Mission.DeploymentPlan.HasDeploymentBoundaries(side);
      if (!(isFirstPlan & flag))
        return;
      foreach ((string id, List<Vec2> points) deploymentBoundary in (List<(string id, List<Vec2> points)>) this.Mission.DeploymentPlan.GetDeploymentBoundaries(side))
        this.AddBoundaryMarkerForSide(side, new KeyValuePair<string, ICollection<Vec2>>(deploymentBoundary.id, (ICollection<Vec2>) deploymentBoundary.points));
    }

    public override void OnRemoveBehavior()
    {
      this.TryRemoveBoundaryMarkers();
      base.OnRemoveBehavior();
    }

    private void AddBoundaryMarkerForSide(
      BattleSideEnum side,
      KeyValuePair<string, ICollection<Vec2>> boundary)
    {
      string key = boundary.Key;
      int index1 = (int) side;
      if (this.boundaryMarkersPerSide[index1].ContainsKey(key))
        return;
      Banner banner1;
      switch (side)
      {
        case BattleSideEnum.Defender:
          banner1 = this.Mission.DefenderTeam.Banner;
          break;
        case BattleSideEnum.Attacker:
          banner1 = this.Mission.AttackerTeam.Banner;
          break;
        default:
          banner1 = (Banner) null;
          break;
      }
      Banner banner2 = banner1;
      List<GameEntity> boundary1 = new List<GameEntity>();
      List<Vec2> list = boundary.Value.ToList<Vec2>();
      for (int index2 = 0; index2 < list.Count; ++index2)
        this.MarkLine(new Vec3(list[index2]), new Vec3(list[(index2 + 1) % list.Count]), boundary1, banner2);
      this.boundaryMarkersPerSide[index1][key] = boundary1;
    }

    private void TryRemoveBoundaryMarkers()
    {
      if (this._boundaryMarkersRemoved)
        return;
      for (int side = 0; side < 2; ++side)
      {
        foreach (string boundaryName in this.boundaryMarkersPerSide[side].Keys.ToList<string>())
          this.RemoveBoundaryMarker(boundaryName, (BattleSideEnum) side);
      }
      this._boundaryMarkersRemoved = true;
    }

    private void RemoveBoundaryMarker(string boundaryName, BattleSideEnum side)
    {
      int index = (int) side;
      List<GameEntity> gameEntityList;
      if (!this.boundaryMarkersPerSide[index].TryGetValue(boundaryName, out gameEntityList))
        return;
      foreach (GameEntity gameEntity in gameEntityList)
        gameEntity.Remove(103);
      this.boundaryMarkersPerSide[index].Remove(boundaryName);
    }

    protected void MarkLine(
      Vec3 startPoint,
      Vec3 endPoint,
      List<GameEntity> boundary,
      Banner banner = null)
    {
      Scene scene = this.Mission.Scene;
      Vec3 vec3_1 = endPoint - startPoint;
      float length = vec3_1.Length;
      Vec3 vec3_2 = vec3_1;
      double num1 = (double) vec3_2.Normalize();
      Vec3 vec3_3 = vec3_2 * this.MarkerInterval;
      for (float num2 = 0.0f; (double) num2 < (double) length; num2 += this.MarkerInterval)
      {
        MatrixFrame identity = MatrixFrame.Identity;
        identity.rotation.RotateAboutUp(vec3_1.RotationZ + 1.57079637f);
        identity.origin = startPoint;
        if (!scene.GetHeightAtPoint(identity.origin.AsVec2, BodyFlags.CommonCollisionExcludeFlagsForCombat, ref identity.origin.z))
          identity.origin.z = 0.0f;
        identity.origin.z -= 0.5f;
        identity.Scale(Vec3.One * 0.4f);
        GameEntity gameEntity = this.entityFactory.MakeEntity((object) banner);
        gameEntity.SetFrame(ref identity);
        boundary.Add(gameEntity);
        startPoint += vec3_3;
      }
    }
  }
}
